﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

using LowLevelGraphics.Filter;

namespace LowLevelGraphics.MultipleSources
{
    /// <summary>
    /// 
    /// </summary>
    public class Interpolation : BaseImageFilter, ITwoSourceFilter
    {
        protected float m_fInterpolation = 0;

        //GetRGB Syntax: 
        //offset + (y-startY)*scansize + (x-startX)

        /// <summary>
        /// Initializes a new instance of the <see cref="Interpolation"/> class.
        /// </summary>
        public Interpolation()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Interpolation"/> class.
        /// </summary>
        /// <param name="_interpolation">The _interpolation.</param>
        internal Interpolation(Interpolation _interpolation)
        {
        }

        /// <summary>
        /// Execute this Filter
        /// A Debug Statement is written if a concrete Filter is called
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            return Process((UnsafeBitmap)_bitmap.Clone(),_bitmap);
        }

        #region ITwoSourceFilter Members

        /// <summary>
        /// Processes the specified bmpimg.
        /// </summary>
        /// <param name="_source"></param>
        /// <param name="_destination"></param>
        /// <returns></returns>
        public UnsafeBitmap Process(UnsafeBitmap _source, UnsafeBitmap _destination)
        {
            int width = _source.Width;
            int height = _source.Height;
            //int type = src.getType();

            if (_destination != null)
            {
                width = Math.Min(width, _destination.Width);
                height = Math.Min(height, _destination.Width);
                Color[,] pixels1 = null;
                Color[,] pixels2 = null;

                for (int y = 0; y < height; y++)
                {
                    pixels1 = GetRGB(_source, 0, y, width, 1);
                    pixels2 = GetRGB(_destination, 0, y, width, 1);
                    for (int x = 0; x < width; x++)
                    {
                        int rgb1 = ColorFunctions.ToIntRGB(pixels1[x,y]); //original: pixels1[x](1d int array)
                        int rgb2 = ColorFunctions.ToIntRGB(pixels2[x,y]); //original: pixels2[x](1d int array)
                        int a1 = (rgb1 >> 24) & 0xff;
                        int r1 = (rgb1 >> 16) & 0xff;
                        int g1 = (rgb1 >> 8) & 0xff;
                        int b1 = rgb1 & 0xff;
                        int a2 = (rgb2 >> 24) & 0xff;
                        int r2 = (rgb2 >> 16) & 0xff;
                        int g2 = (rgb2 >> 8) & 0xff;
                        int b2 = rgb2 & 0xff;
                        r1 = ImageMath.Clamp(ImageMath.LinearInterpolate(m_fInterpolation, r1, r2));
                        g1 = ImageMath.Clamp(ImageMath.LinearInterpolate(m_fInterpolation, g1, g2));
                        b1 = ImageMath.Clamp(ImageMath.LinearInterpolate(m_fInterpolation, b1, b2));
                        pixels1[x, y] = Color.FromArgb((a1 << 24) | (r1 << 16) | (g1 << 8) | b1); //original: pixels2[x](1d int array)
                    }
                    SetRGB(_destination, 0, y, width, 1, pixels1);
                }
            }
            return _destination;
        }

        #endregion

        /// <summary>
        /// Gets the RGB.
        /// </summary>
        /// <param name="_bitmap">The _bitmap.</param>
        /// <param name="_nXStart">The _n X start.</param>
        /// <param name="_nYStart">The _n Y start.</param>
        /// <param name="_nWidth">Width of the _n.</param>
        /// <param name="_nHeight">Height of the _n.</param>
        /// <returns></returns>
        public Color[,] GetRGB(UnsafeBitmap _bitmap, int _nXStart, int _nYStart, int _nWidth, int _nHeight)
        {
            Color[,] aColor = new Color[_nWidth, _nHeight];
            int x=0;
            int y=0;
            for (y = _nYStart; y < _nYStart + _nHeight; y++)
            {
                for (x = _nXStart; x < _nXStart + _nWidth; x++)
                {
                    aColor[x, y] = _bitmap[x, y];
                }
            }
            return aColor;
        }

        /// <summary>
        /// Sets the RGB.
        /// </summary>
        /// <param name="_bitmap">The _bitmap.</param>
        /// <param name="_nXStart">The _n X start.</param>
        /// <param name="_nYStart">The _n Y start.</param>
        /// <param name="_nWidth">Width of the _n.</param>
        /// <param name="_nHeight">Height of the _n.</param>
        /// <param name="_aColor">Color of the _a.</param>
        public void SetRGB(UnsafeBitmap _bitmap, int _nXStart, int _nYStart, int _nWidth, int _nHeight, Color[,] _aColor)
        {
            Color[,] aColor = new Color[_nWidth, _nHeight];
            int x = 0;
            int y = 0;
            for (y = _nYStart; y < _nYStart + _nHeight; y++)
            {
                for (x = _nXStart; x < _nXStart + _nWidth; x++)
                {
                    _bitmap[x, y] = aColor[x-_nXStart, y-_nYStart];
                }
            }
        }

        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new Interpolation(this);
        }
    }
}
